package com.mp.approvalreq.servlet;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.managerplus.key.service.KeyGeneratorServicePrx;
import com.mp.approvalreq.entity.*;
import com.mp.approvalreq.entity.common.Constants;
import com.mp.approvalreq.entity.dto.TemplateDTO;
import com.mp.approvalreq.entity.message.TemplateMsg;
import com.mp.approvalreq.service.ReadTemplateServicePrx;
import com.mp.approvalreq.service.SelectApprovalServicePrx;
import com.mp.approvalreq.util.*;
import com.mp.user.entity.User;
import com.mp.user.service.UserServicePrx;
import com.plusmoney.exception.RpcServerLogicalException;
import com.plusmoney.mq.MQProducer;
import com.plusmoney.util.Utils;
import com.qq.tars.client.util.ServantUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 公司修改模板生成新模板
 *
 * @author Administrator
 */
@WebServlet("/settingNewOriginTemplate")
public class SettingNewOriginTemplate extends AbstractServlet {

    private static final long serialVersionUID = -6524473373623928868L;

    private static final Logger logger = LoggerFactory.getLogger(SettingNewOriginTemplate.class);

    @Override
    public void init() throws ServletException {
        super.init();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        try {
            User user = getReqUser(req);

            if (!ApprovalUtils.isApprovalAdmin(user)) {
                throw new RpcServerLogicalException(1, "无权操作");
            }

            Integer userGeneration = getUserGeneration(req);

            Template template = getTemplate(req);
            check(template, userGeneration);

            checkGenerationWithTemplate(userGeneration, template);

            // 检测是否是老版本修改模板
            if (template.getTemplateId() != 0) {
                SelectApprovalServicePrx selectApprovalService = ServiceUtils.getSelectApprovalServicePrx();
                TemplateDTO templateDTO = selectApprovalService.getTemplateDTO(user.getCompanyId(), template.getTemplateId());
                if (ApprovalUtils.checkNotAuthGeneration(userGeneration, templateDTO.getGeneration())) {
                    throw new RpcServerLogicalException(1, "请更新大管加版本");
                }
            }

            KeyGeneratorServicePrx keyGeneratorService = ServantUtils.getObject(KeyGeneratorServicePrx.class);
            int templatePrimaryKey = keyGeneratorService.generateKey("requestTemplate");
            logger.info("模板id:{}", templatePrimaryKey);
            template.setTemplateInsertId(templatePrimaryKey);

            // 模板版本
            Integer setGeneration = ComponentGenerationUtils.getTemplateGeneration(template);

            ReadTemplateServicePrx readTemplateServicePrx = ServiceUtils.getReadTemplateServicePrx();
            readTemplateServicePrx.settingNewOriginTemplate(template, user, setGeneration);

            // 发送消息
            sendTemplateTempCcMsg(template, user.getCompanyId());

            returnResult(resp);
        } catch (Throwable e) {
            onThrowable(req, resp, e);
        }
    }

    private void sendTemplateTempCcMsg(Template template, Integer companyId) {
        if (template.getTemplateId() != 0) {
            TemplateMsg msg = new TemplateMsg();
            msg.setCompanyId(companyId);
            msg.setTemplateId(template.getTemplateId());
            msg.setOperateFlag(template.getIsAllowAddTempCc());

            logger.info("修改模板消息:{} ", msg.toString());
            try {
                MQProducer.send(Constants.MQ_APPROVAL_TOPIC, Constants.MQ_TAGS_UPDATE_TEMPLATE, msg);
            } catch (Throwable e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    private void returnResult(HttpServletResponse resp) throws IOException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result", "0");
        jsonObject.put("res_info", "成功");
        logger.info(jsonObject.toJSONString());

        printJson(resp, jsonObject.toJSONString());
    }


    /**
     * @param generation
     * @param template
     */
    private void checkGenerationWithTemplate(Integer generation, Template template) {
        List<TemplateComponent> templateComponents = getTemplateComponentList(template);
        if (!ComponentGenerationUtils.checkGenerationComponent(templateComponents, generation, template)) {
            throw new RpcServerLogicalException(1, "请升级大管加版本");
        }
    }

    private Template getTemplate(HttpServletRequest req) throws IOException {
        String reqBody = getContent(req);
        logger.info(String.format("公司修改默认模板生成新模板：json参数值：%s", reqBody));

        Template template;
        try {
            template = JSONObject.parseObject(reqBody, Template.class);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new RpcServerLogicalException(1, "客户端请求参数格式错误");
        }
        return template;
    }

    private void check(Template template, Integer generation) throws Throwable {
        List<TemplateComponent> templateComponents = getTemplateComponentList(template);

        checkTemplateComponent(templateComponents);

        checkNewCheckInTemplate(template, templateComponents);

        if (generation < Constants.DEFAULT_GENERATION) {
            checkMontyComponentSize(templateComponents);
        }

        checkTemplateName(template);

        checkTemplateRange(template);

        checkRequestFlow(template);

        checkMultiChosen(template);

        specialLogic(template);

    }

    private void checkMultiChosen(Template template) {
        if (StringUtils.isNotEmpty(template.getMultiChosen())) {
            List<String> chosenList = JSONArray.parseArray(template.getMultiChosen(), String.class);
            if (Utils.isNotEmpty(chosenList)) {
                for (String chosenItem : chosenList) {
                    JSONObject jsonObject = JSON.parseObject(chosenItem);
                    JSONArray jsonArray = jsonObject.getJSONArray("content");
                    if (Utils.isEmpty(jsonArray)) {
                        throw new RpcServerLogicalException(1, "单选项格式错误");
                    }
                    for (int i = 0; i < jsonArray.size(); i++) {
                        String content = jsonArray.getString(i);
                        if (content.length() > 60) {
                            logger.info("长度:{}", chosenItem);
                            throw new RpcServerLogicalException(1, "单选项字数不得超过60个字");
                        }
                    }
                }
            }
        }

    }

    private void specialLogic(Template template) {
        if (Utils.isNull(template.getAmountTop())) {
            template.setAmountTop(BigDecimal.ZERO);
        }
    }


    private void checkTemplateComponent(List<TemplateComponent> templateComponents) {
        int clientCount = ComponentUtils.countByContentType(templateComponents, ContentType.RELATED_CLIENT);
        if (clientCount > 1) {
            throw new RpcServerLogicalException(1, "一个模板最多拥有一个关联客户组件");
        }
        int approvalCount = ComponentUtils.countByContentType(templateComponents, ContentType.RELATED_APPROVAL);
        if (approvalCount > 1) {
            throw new RpcServerLogicalException(1, "一个模板最多拥有一个关联审批组件");
        }
        int approvalTask = ComponentUtils.countByContentType(templateComponents, ContentType.RELATED_TASK);
        if (approvalTask > 1) {
            throw new RpcServerLogicalException(1, "一个模板最多拥有一个关联任务组件");
        }
        int approvalNeedMoney = ComponentUtils.countByContentType(templateComponents, ContentType.RELATED_NEED_MONEY);
        if (approvalNeedMoney > 1) {
            throw new RpcServerLogicalException(1, "一个模板最多拥有一个关联申购组件");
        }
    }

    /**
     * if (template.getRequestFlow().contains("DM")) {
     * // xx,DM,xx; 这种情况不允许,前端有几个版本没有限制,后台限制下
     * String[] flowArr = template.getRequestFlow().split(",");
     * if (!Objects.equals(flowArr[0], RequestFlowType.SP_DEFINE)) {
     * throw new RpcServerLogicalException(1, "如第一层审批人不是直接上级，则第二层不能设置为间接上级");
     * }
     * }
     */
    private void checkRequestFlow(Template template) {
        if (StringUtils.isEmpty(template.getRequestFlow())) {
            if (Utils.isNull(template.getIsAllowedToEditJudger()) || template.getIsAllowedToEditJudger() == 0) {
                throw new RpcServerLogicalException(1, "请设置审批流程");

            } else {
                // 前端老版本不会传该字段
                template.setRequestFlow(RequestFlowType.ALTERNATIVE);
            }

        } else if (Objects.equals("Condition", template.getRequestFlow())) {
            if (ListHelper.isNullEmpty(template.getConditionFlow())) {
                throw new RpcServerLogicalException(1, "请设置条件判断审批流的判断条件");
            }
        }
    }

    private void checkTemplateRange(Template template) throws Throwable {
        if (StringUtils.isEmpty(template.getDepartmentId())) {
            if (StringUtils.isEmpty(template.getRangeSpecific())) {
                throw new RpcServerLogicalException(1, "请选择适用范围");
            }

            // 前端会给空字符,这里帮它置为-1
            template.setDepartmentId("-1");
        }

        if (StringUtils.isNotEmpty(template.getRangeSpecific())) {
			/*
			     将rangeSpecific人群的companyInfoId也都取出来;
			     前端rangeSpecific的数据会存在离职的,因为如果只是修改其它数据,则适用人群只是回显
			 */
            UserServicePrx userService = ServantUtils.getObject(UserServicePrx.class);
            List<User> users = userService.getUserListByContactIds(template.getRangeSpecific());

            if (ListHelper.isNullEmpty(users)) {
                throw new RpcServerLogicalException(1, "请选择适用范围");
            }

            String contactIds = ListHelper.getContactIds(users);
            String companyInfoIdRang = getCompanyInfoIdRang(users, contactIds);

            template.setRangeSpecific(contactIds);
            template.setCompanyInfoIdRange(companyInfoIdRang);
        }
    }

    private String getCompanyInfoIdRang(List<User> users, String contactIds) {
        List<Integer> companyInfoIds = new ArrayList<>(users.size());

        for (String contactId : contactIds.split(",")) {
            for (User user : users) {
                if (contactId.equals(user.getContactId().toString())) {
                    if (!companyInfoIds.contains(user.getCompanyInfoId())) {
                        companyInfoIds.add(user.getCompanyInfoId());
                    }
                    break;
                }
            }
        }

        return ListHelper.list2string(companyInfoIds);
    }

    private void checkTemplateName(Template template) {
        if (StringUtils.isEmpty(template.getTemplateMetaName()) && StringUtils.isEmpty(template.getTemplateName())) {
            throw new RpcServerLogicalException(1, "请输入模板名");

        } else {

            if (StringUtils.isEmpty(template.getTemplateMetaName())) {
                template.setTemplateMetaName(template.getTemplateName());
            }

            if (StringUtils.isEmpty(template.getTemplateName())) {
                template.setTemplateName(template.getTemplateMetaName());
            }
        }
    }

    private List<TemplateComponent> getTemplateComponentList(Template template) {
        List<TemplateComponent> templateComponents;
        try {
            templateComponents = JSONArray.parseArray(template.getTemplateComponent(), TemplateComponent.class);
        } catch (Exception e) {
            throw new RpcServerLogicalException(1, "数据格式错误");
        }

        if (ListHelper.isNullEmpty(templateComponents)) {
            throw new RpcServerLogicalException(1, "模板内容为空");
        }
        return templateComponents;
    }


    private void checkMontyComponentSize(List<TemplateComponent> list) {
        int size = 0;
        for (TemplateComponent tc : list) {
            if (tc.getType() == 0) {
                throw new RpcServerLogicalException(1, "模板组件类型为空");
            }
            // 一个模板只能拥有一个金额组件
            if (tc.getType() == ContentType.MONEY) {
                size++;
            }
        }
        if (size > 1) {
            throw new RpcServerLogicalException(1, "一个模板最多拥有一个金额组件");
        }
    }

    /**
     * 补打卡模板只有更新最新的版本才能修改
     *
     * @param template
     * @param list
     */
    private void checkNewCheckInTemplate(Template template, List<TemplateComponent> list) {
        if (template.getDefaultType() == Template.APPEND_SIGN) {
            for (TemplateComponent component : list) {
                if (component.getNum() == 2) {
                    if (component.getType() != ContentType.RECEIVE_CLOCK_TYPE) {
                        throw new RpcServerLogicalException(1, "请先更新大管加版本，再修改补卡申请模板");
                    }
                }
            }
        }
    }


}
